package com.javaspeak.designpatterns.go4.behavioural.interpreter;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/**
 * Used for parsing select "Object Query Language (oql)" statements.
 *
 * @author John Dickerson
 */
public class SelectExpression extends AbstractExpression {

    // select statement to parse
    private String selectStatement;

    // select statement is passed through constructor
    public SelectExpression( String selectStatement ){

        this.selectStatement = selectStatement;
    }

    /* (non-Javadoc)
     * @see com.javaspeak.designpatterns.go4.behavioural.interpreter.
     *      AbstractExpression#interpret(com.javaspeak.designpatterns.go4.
     *              behavioural.interpreter.InterpreterContext)
     */
    @Override
    public List<Value> interpret(InterpreterContext context) throws Exception {

        // tokenize statement using spaces and commas as seperators
        StringTokenizer wordTokenizer =
            new StringTokenizer( selectStatement,", " );

        // the first token is "select"
        wordTokenizer.nextToken();

        String tokenString;

        // creates a list to hold the fieldNames
        List<String> fieldNames =
            new ArrayList<String>( wordTokenizer.countTokens() );

        // add all tokens before the toek "from" to the fieldNames list
        while (  wordTokenizer.hasMoreTokens() &&
              ! ( tokenString = wordTokenizer.nextToken() ).equals( "from" ) ){

            fieldNames.add( tokenString );
        }

        // the next token is the className
        String className = wordTokenizer.nextToken();

        // initialize the list of field values to return
        List<Value> fieldValues = new ArrayList<Value>( fieldNames.size() );

        Value value;

        for ( String fieldName : fieldNames ){

            // make a call to the InterpreterContext to retrieve the field value
            // for the field in the specified object registered with the
            // InterpreterContext
            value = new Value( context.getFieldValue( className, fieldName ) );

            // add the field value to the list of Values to return.
            fieldValues.add( value );
        }

        // return the field values
        return fieldValues;
    }
}
